今儿回过头来,继续这里的文章。那句话是怎么说的:

    自己选择的课题,含着泪也得磕完!”(图文无关,)。

    其实在上一篇libevent文章中(《PHP socket初探 —- 硬着头皮继续libevent(二)》),如果你总结能力很好的话,可以观察出来我们尝试利用libevent做了至少两件事情:

    • 信号监听工具

    大家都是码php的,也喜欢把自己说的洋气点儿:“ 我是写服务器的 ”。所以,今天的第一个案例就是拿libevent来构建一个简单粗暴的http服务器:

    将代码保存为test.php,然后php http.php运行起来。再开一个终端,使用curl的GET方式去请求服务器,效果如下:

    这是一个非常非常简单地不能再简单的http demo了,对于一个完整的http服务器而言,他还差比较完整的http协议的实现、多核CPU的利用等等。这些,我们会放到后面继续深入的文章中开始细化丰富。

    还记得我们使用select系统调用实现了一个粗暴的在线聊天室,select这种业余的都敢出来混个聊天室,专业的绝对不能怂。

    无数个专业👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍送给libevent!

    14. PHP socket初探 —- 含着泪也要磕完libevent(三) - 图1

    14. PHP socket初探 —- 含着泪也要磕完libevent(三) - 图2

    1. $host = '0.0.0.0';
    2. $port = 9999;
    3. $fd = socket_create( AF_INET, SOCK_STREAM, SOL_TCP );
    4. socket_bind( $fd, $host, $port );
    5. socket_listen( $fd );
    6. // 注意,将“监听socket”设置为非阻塞模式
    7. socket_set_nonblock( $fd );
    8. // 这里值得注意,我们声明两个数组用来保存 事件 和 连接socket
    9. $event_arr = [];
    10. $conn_arr = [];
    11. $event_base = new EventBase();
    12. $event = new Event( $event_base, $fd, Event::READ | Event::PERSIST, function( $fd ){
    13. // 使用全局的event_arr 和 conn_arr
    14. global $event_arr,$conn_arr,$event_base;
    15. // 非阻塞模式下,注意accpet的写法会稍微特殊一些。如果不想这么写,请往前面添加@符号,不过不建议这种写法
    16. if( ( $conn = socket_accept( $fd ) ) != false ){
    17. echo date('Y-m-d H:i:s').':欢迎'.intval( $conn ).'来到聊天室'.PHP_EOL;
    18. // 将连接socket也设置为非阻塞模式
    19. socket_set_nonblock( $conn );
    20. // 此处值得注意,我们需要将连接socket保存到数组中去
    21. $conn_arr[ intval( $conn ) ] = $conn;
    22. $event = new Event( $event_base, $conn, Event::READ | Event::PERSIST, function( $conn ) {
    23. $buffer = socket_read( $conn, 65535 );
    24. foreach( $conn_arr as $conn_key => $conn_item ){
    25. if( $conn != $conn_item ){
    26. $msg = intval( $conn ).'说 : '.$buffer;
    27. socket_write( $conn_item, $msg, strlen( $msg ) );
    28. }
    29. }
    30. }, $conn );
    31. $event->add();
    32. // 此处值得注意,我们需要将事件本身存储到全局数组中,如果不保存,连接会话会丢失,也就是说服务端和客户端将无法保持持久会话
    33. $event_arr[ intval( $conn ) ] = $event;
    34. }
    35. }, $fd );

    将代码保存为server.php,然后php server.php运行,再打开其他三个终端使用telnet连接上聊天室,运行效果如下所示:

    尝试放一张动态图试试,看看行不行,自己制作的gif都特别大,不知道带宽够不够。

    14. PHP socket初探 —- 含着泪也要磕完libevent(三) - 图3

    截止到这篇为止,死磕Libevent系列的大体核心三把斧就算是抡完了,弄完这些,你在遇到这些代码的时候,就应该不会像下面这个样子了: